// © SCOTTGO
//@version=6
indicator("SCOTTGO - Liquidity Zones V10.1 (Comprehensive Tooltips)", overlay=true, max_lines_count=500, max_boxes_count=500, max_labels_count=500)

// -----------------------------------------------------------------------------
// 1. CORE LOGIC & INTRADAY FILTERS
// -----------------------------------------------------------------------------
pivotLen   = input.int(14, "Pivot Lookback", group="Core Logic")
atrPeriod  = input.int(14, "ATR Offset Period", group="Core Logic")
baseOffset = input.float(3.5, "Label Distance", group="Core Logic")

// --- Intraday Control ---
useLookback = input.bool(true, "Enable Bar Lookback (Recommended)", group="Intraday Optimization")
lookbackLen = input.int(500, "Lookback Period (Bars)", minval=50, group="Intraday Optimization", tooltip="Only tracks liquidity from the last X bars. 390 bars = 1 trading day on 1m chart.")

// -----------------------------------------------------------------------------
// 2. STYLING & TOGGLES
// -----------------------------------------------------------------------------
showLIQText = input.bool(true, "Show Price (LIQ) Labels", group="Zone Features", tooltip="Toggle the visibility of the LIQ price tags. Tooltips remain accessible on the Zone labels.")
zoneSize    = input.string("Normal", "Font Size", options=["Tiny", "Small", "Normal", "Large"], group="Zone Features")

// --- LIQ Line (Pivot Level) ---
showLIQ = input.bool(true, "", inline="liq", group="LIQ Line Settings")
liqCol  = input.color(color.new(color.white, 40), "LIQ Line ", inline="liq", group="LIQ Line Settings")
liqWid  = input.int(1, "", minval=1, maxval=4, inline="liq", group="LIQ Line Settings")
liqSty  = input.string("Solid", "", options=["Solid", "Dashed", "Dotted"], inline="liq", group="LIQ Line Settings")

// --- Sweep Styles ---
showBSw = input.bool(true, "", inline="bsw", group="Bear Sweep Style")
bswCol  = input.color(color.new(#f23645, 0), "Bear Swp ", inline="bsw", group="Bear Sweep Style")
bswWid  = input.int(2, "", minval=1, maxval=4, inline="bsw", group="Bear Sweep Style")
bswSty  = input.string("Solid", "", options=["Solid", "Dashed", "Dotted"], inline="bsw", group="Bear Sweep Style")

showUSw = input.bool(true, "", inline="usw", group="Bull Sweep Style")
uswCol  = input.color(color.new(#089981, 0), "Bull Swp ", inline="usw", group="Bull Sweep Style")
uswWid  = input.int(2, "", minval=1, maxval=4, inline="usw", group="Bull Sweep Style")
uswSty  = input.string("Solid", "", options=["Solid", "Dashed", "Dotted"], inline="usw", group="Bull Sweep Style")

// --- Colors ---
bullZoneCol = input.color(color.new(#089981, 85), "Bull Zone BG", group="Colors")
bearZoneCol = input.color(color.new(#f23645, 85), "Bear Zone BG", group="Colors")
mitigateCol = input.color(color.new(color.gray, 90), "Mitigated BG", group="Colors")

// -----------------------------------------------------------------------------
// 3. ENGINE
// -----------------------------------------------------------------------------
f_getSize(s) =>
    switch s
        "Tiny"   => size.tiny
        "Small"  => size.small
        "Normal" => size.normal
        "Large"  => size.large

f_getStyle(s) =>
    switch s
        "Solid"  => line.style_solid
        "Dashed" => line.style_dashed
        "Dotted" => line.style_dotted

type LiquidityLevel
    float price
    int   createdBar
    bool  active = true
    box   bx
    label infoLbl
    label titleLbl
    line  liqLine

var levelsH = array.new<LiquidityLevel>()
var levelsL = array.new<LiquidityLevel>()
atrVal = ta.atr(atrPeriod)

ph = ta.pivothigh(pivotLen, pivotLen)
pl = ta.pivotlow(pivotLen, pivotLen)

// --- Cleanup Routine ---
f_cleanup(_arr) =>
    if useLookback and array.size(_arr) > 0
        for i = array.size(_arr) - 1 to 0
            lvl = array.get(_arr, i)
            if (bar_index - lvl.createdBar) > lookbackLen
                box.delete(lvl.bx)
                label.delete(lvl.infoLbl)
                label.delete(lvl.titleLbl)
                line.delete(lvl.liqLine)
                array.remove(_arr, i)

if bar_index % 20 == 0
    f_cleanup(levelsH)
    f_cleanup(levelsL)

// --- Bear Zone Creation ---
if not na(ph)
    string liqTip = "LIQUIDITY LEVEL (Pivot High)\n" + "Price: " + str.tostring(ph, "#.##") + "\nCreated at Bar: " + str.tostring(bar_index - pivotLen) + "\nStatus: Active Resistance"
    string zoneTip = "BEARISH LIQUIDITY ZONE\n" + "Type: Resistance / Supply\n" + "This zone represents a cluster of Buy-Side Liquidity (Stop Losses) sitting above a recent structural high. Traders look for sweeps or reversals here."
    
    box b = box.new(bar_index - pivotLen, ph, bar_index, math.max(open[pivotLen], close[pivotLen]), bgcolor=bearZoneCol, border_color=na)
    label l = label.new(bar_index - pivotLen, ph + (atrVal * baseOffset), showLIQText ? "LIQ\n" + str.tostring(ph, "#.##") : "", color=color.new(color.white, 100), textcolor=color.new(color.white, 40), style=label.style_label_down, size=f_getSize(zoneSize), tooltip=liqTip)
    label tl = label.new(bar_index - pivotLen, ph, "BEAR ZONE", color=color.new(color.white, 100), textcolor=color.new(color.white, 50), style=label.style_label_center, size=f_getSize(zoneSize), tooltip=zoneTip)
    line hL = line.new(bar_index - pivotLen, ph, bar_index, ph, color=showLIQ ? liqCol : na, width=liqWid, style=f_getStyle(liqSty))
    array.push(levelsH, LiquidityLevel.new(ph, bar_index - pivotLen, true, b, l, tl, hL))

// --- Bull Zone Creation ---
if not na(pl)
    string liqTip = "LIQUIDITY LEVEL (Pivot Low)\n" + "Price: " + str.tostring(pl, "#.##") + "\nCreated at Bar: " + str.tostring(bar_index - pivotLen) + "\nStatus: Active Support"
    string zoneTip = "BULLISH LIQUIDITY ZONE\n" + "Type: Support / Demand\n" + "This zone represents a cluster of Sell-Side Liquidity (Stop Losses) sitting below a recent structural low. Traders look for liquidity grabs or bounces here."

    box b = box.new(bar_index - pivotLen, math.min(open[pivotLen], close[pivotLen]), bar_index, pl, bgcolor=bullZoneCol, border_color=na)
    label l = label.new(bar_index - pivotLen, pl - (atrVal * baseOffset), showLIQText ? "LIQ\n" + str.tostring(pl, "#.##") : "", color=color.new(color.white, 100), textcolor=color.new(color.white, 40), style=label.style_label_up, size=f_getSize(zoneSize), tooltip=liqTip)
    label tl = label.new(bar_index - pivotLen, pl, "BULL ZONE", color=color.new(color.white, 100), textcolor=color.new(color.white, 50), style=label.style_label_center, size=f_getSize(zoneSize), tooltip=zoneTip)
    line hL = line.new(bar_index - pivotLen, pl, bar_index, pl, color=showLIQ ? liqCol : na, width=liqWid, style=f_getStyle(liqSty))
    array.push(levelsL, LiquidityLevel.new(pl, bar_index - pivotLen, true, b, l, tl, hL))

// --- Bear Sweep Processing ---
for lvl in levelsH
    if lvl.active
        box.set_right(lvl.bx, bar_index)
        line.set_x2(lvl.liqLine, bar_index)
        if high > lvl.price and close < lvl.price and showBSw
            float targetY = high + (atrVal * 1.2)
            string sweepTip = "BEARISH SWEEP DETECTED\n" + "Price pierced the Liquidity Level at " + str.tostring(lvl.price, "#.##") + " but failed to close above it.\n" + "High of Sweep: " + str.tostring(high, "#.##") + "\n" + "Interpretation: Sellers are defending this level; potential fake-out/reversal."
            label.new(bar_index, targetY, "SWEEP", color=bswCol, textcolor=color.white, style=label.style_label_down, size=f_getSize(zoneSize), tooltip=sweepTip)
            line.new(bar_index, high, bar_index, targetY, color=bswCol, width=bswWid, style=f_getStyle(bswSty))
        if close > lvl.price
            lvl.active := false
            string mitTip = "ZONE MITIGATED\n" + "Invalidated: Price closed above the pivot level at " + str.tostring(lvl.price, "#.##") + ".\n" + "Mitigation Bar: " + str.tostring(bar_index) + "\n" + "Status: This zone is no longer considered a strong liquidity pool."
            box.set_bgcolor(lvl.bx, mitigateCol)
            label.set_text(lvl.titleLbl, "MITIGATED")
            label.set_tooltip(lvl.titleLbl, mitTip)
            label.set_tooltip(lvl.infoLbl, "Status: Mitigated/Inactive\nLevel: " + str.tostring(lvl.price, "#.##"))
            if not showLIQText
                label.delete(lvl.infoLbl)
            else
                label.set_text(lvl.infoLbl, "")
            line.set_color(lvl.liqLine, na)

// --- Bull Sweep Processing ---
for lvl in levelsL
    if lvl.active
        box.set_right(lvl.bx, bar_index)
        line.set_x2(lvl.liqLine, bar_index)
        if low < lvl.price and close > lvl.price and showUSw
            float targetY = low - (atrVal * 1.2)
            string sweepTip = "BULLISH SWEEP DETECTED\n" + "Price pierced the Liquidity Level at " + str.tostring(lvl.price, "#.##") + " but failed to close below it.\n" + "Low of Sweep: " + str.tostring(low, "#.##") + "\n" + "Interpretation: Buyers are defending this level; potential fake-out/reversal."
            label.new(bar_index, targetY, "SWEEP", color=uswCol, textcolor=color.white, style=label.style_label_up, size=f_getSize(zoneSize), tooltip=sweepTip)
            line.new(bar_index, low, bar_index, targetY, color=uswCol, width=uswWid, style=f_getStyle(uswSty))
        if close < lvl.price
            lvl.active := false
            string mitTip = "ZONE MITIGATED\n" + "Invalidated: Price closed below the pivot level at " + str.tostring(lvl.price, "#.##") + ".\n" + "Mitigation Bar: " + str.tostring(bar_index) + "\n" + "Status: This zone is no longer considered a strong liquidity pool."
            box.set_bgcolor(lvl.bx, mitigateCol)
            label.set_text(lvl.titleLbl, "MITIGATED")
            label.set_tooltip(lvl.titleLbl, mitTip)
            label.set_tooltip(lvl.infoLbl, "Status: Mitigated/Inactive\nLevel: " + str.tostring(lvl.price, "#.##"))
            if not showLIQText
                label.delete(lvl.infoLbl)
            else
                label.set_text(lvl.infoLbl, "")
            line.set_color(lvl.liqLine, na)